﻿// Copyright (c) 2012 - 2020 Jared Zheng <jaredz at outlook dot com>
// Buddha Framework is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of Mulan PSL v2 at:
//          http://license.coscl.org.cn/MulanPSL2
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
// MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
// See the Mulan PSL v2 for more details.
//
// Create : 2012-12-01 version 0.1 Jared Zheng <jaredz at outlook dot com>
// Update : 2018-12-05 version 3.1.5 Jared Zheng <jaredz at outlook dot com>

#include "stdafx.h"
#include "MasterDBServerImp.h"

///////////////////////////////////////////////////////////////////////////////////////////////////////////
// CMasterDBServer
UInt CMasterDBServer::Command(PCXStr pszCMD, uintptr_t utParam)
{
    CString strCmd = pszCMD;
    if (strCmd == TF("ServerInfo"))
    {
        m_nServerInfo = (Int)utParam;
    }
    else if (strCmd == TF("ServerAck"))
    {
        m_nServerAck = (Int)utParam;
    }
    else if (strCmd == TF("SyncInfo"))
    {
        m_nSyncInfo = (Int)utParam;
    }
    else if (strCmd == TF("CommonEvent"))
    {
        m_nCommonEvent = (Int)utParam;
    }
    return (UInt)RET_OKAY;
}

UInt CMasterDBServer::Update(void)
{
    if (m_nStatus < STATUSS_ERROR)
    {
        // 定时更新线程异常导致不向同步管理发送心跳包, 会导致本服务器离线
        // 这里只要测试网络工作线程的异常就可以了
        if (m_NetworkPtr->Check(m_pConfig->GetUpdateTick() * DATAD_TIME))
        {
            m_ServerInfo.MayDay(); // 网络工作线程异常
            m_nStatus = STATUSS_ERROR;
            DEV_ERROR(TF("[业务数据]网络线程异常, 进入异常状态"));
            LOG_ERROR(m_FileLog, TF("[业务数据]网络线程异常, 进入异常状态"));
        }

        CheckConnectCenterServer();
        CheckListen();
        m_RoutinePtr->Update();
    }
    if (m_nStatus < STATUSS_STOP)
    {
        if (SyncServerInfo())
        {
            // unlink : tick thread exception
            // mayday : network & eventqueue thread exception
            // warn   : tcp listen
            return RET_OKAY;
        }
    }
    return RET_FAIL;
}
//--------------------------------------
UInt CMasterDBServer::Init(CEventHandler& EventHandlerRef, CServerConfig& ConfigRef)
{
    if (m_nStatus == STATUSS_NONE)
    {
        m_FileLog.Create(ConfigRef.GetLogPath(), CServerConfig::MasterDBServer);
        LOG_INFO(m_FileLog, TF("[业务数据]初始化开始!"));
        m_MgrHandler = &EventHandlerRef;
        m_pConfig    = &ConfigRef;

        if (LoadConfig() == false)
        {
            return (UInt)RET_FAIL;
        }

        m_nStatus = STATUSS_INIT;
        LOG_INFO(m_FileLog, TF("[业务数据]初始化完成!"));
        return (UInt)RET_OKAY;
    }
    return (UInt)RET_FAIL;
}

bool CMasterDBServer::LoadConfig(void)
{
    assert(m_pConfig != nullptr);
    m_pConfig->Dump(m_FileLog, CServerConfig::CFG_LOAD_MASTERDB); // 配置信息输出到日志文件
    // 从动态变量表获取网络层智能指针
    assert(m_NetworkPtr == nullptr);
    CKeyValue::VALUE xValue = {0};
    m_pConfig->GetKeyValue().GetValue(CServerConfig::NetworkPtr, xValue);
    if (xValue.pValue == nullptr)
    {
        LOG_ERROR(m_FileLog, TF("[业务数据]从动态变量表获取网络层智能指针无效"));
        return false;
    }
    m_NetworkPtr = *(reinterpret_cast<CNetworkPtr*>(xValue.pValue));
    // 保存业务数据指针到动态变量表
    m_pConfig->GetKeyValue().AddItem(CServerConfig::MasterDBServer, this);

    assert(m_sConnectCenter  == 0);
    assert(m_sListenInternal == 0);

    assert(m_Master.SvrMap.GetSize()  == 0);
    assert(m_Service.SvrMap.GetSize() == 0);

    m_ServerInfo.usId   = m_pConfig->GetServerId(CServerConfig::CFG_LOAD_MASTERDB);
    m_ServerInfo.usIncr = m_pConfig->GetServerIncr(CServerConfig::CFG_LOAD_MASTERDB);
    LOGV_INFO(m_FileLog, TF("[业务数据]从配置读取服务器Id=%d, Incr=%d!"), m_ServerInfo.usId, m_ServerInfo.usIncr);
    if (m_pConfig->GetNetworkAttr() & ATTR_IPV6)
    {
        m_ServerInfo.NetAddr[COMMONI_ANY].usAttr = ATTR_IPV6;
    }

    STR_ADDR strAddr;
    m_pConfig->GetServerAddr(CServerConfig::CFG_LOAD_MASTERDB, CServerConfig::CFG_LOAD_NONE, strAddr);
    m_NetworkPtr->TranslateAddr(strAddr.strIp, strAddr.usPort, m_ServerInfo.NetAddr[COMMONI_ANY]);

    if (LoadExtConfig())
    {
        return true;
    }
    LOG_ERROR(m_FileLog, TF("[业务数据]创建例程处理失败"));
    return false;
}
//--------------------------------------
void CMasterDBServer::Exit(void)
{
    if (m_nStatus != STATUSS_NONE)
    {
        LOG_INFO(m_FileLog, TF("[业务数据]退出处理开始!"));
        m_MgrHandler = nullptr;

        UnloadConfig();

        m_nStatus = STATUSS_NONE;
        LOG_INFO(m_FileLog, TF("[业务数据]退出处理完成!"));
    }
}

void CMasterDBServer::UnloadConfig(void)
{
    m_pConfig    = nullptr;
    m_NetworkPtr = nullptr;

    assert(m_sConnectCenter  == 0);
    assert(m_sListenInternal == 0);

    assert(m_Master.SvrMap.GetSize()  == 0);
    assert(m_Service.SvrMap.GetSize() == 0);
    //m_pConfig->GetKeyValue().Remove(CServerConfig::MasterDBServer);

    UnloadExtConfig();
}
//--------------------------------------
bool CMasterDBServer::Start(void)
{
    if (m_nStatus == STATUSS_INIT)
    {
        LOG_INFO(m_FileLog, TF("[业务数据]启动开始!"));

        if (m_RoutinePtr->Start(this) == false)
        {
            return false;
        }
        if ((StartConnectCenterServer() == false) ||
            (StartListen() == false))
        {
            return false;
        }

        m_nStatus = STATUSS_RUN;
        LOG_INFO(m_FileLog, TF("[业务数据]启动完成!"));
    }
    return true;
}

bool CMasterDBServer::StartConnectCenterServer(void)
{
    if (m_sConnectCenter == 0)
    {
        STR_ADDR  strAddr;
        m_pConfig->GetServerAddr(CServerConfig::CFG_LOAD_MASTERDB, CServerConfig::CFG_LOAD_CENTER, strAddr);
        m_sConnectCenter = m_NetworkPtr->Create(*this, strAddr.usPort, *strAddr.strIp);
    }
    if (m_sConnectCenter != 0)
    {
        LOG_INFO(m_FileLog, TF("[业务数据]创建连接同步管理服务器Socket成功"));
        if (m_nCenterLink == STATUSL_NONE)
        {
            STR_ADDR  strAddr;
            m_pConfig->GetServerAddr(CServerConfig::CFG_LOAD_CENTER, CServerConfig::CFG_LOAD_NONE, strAddr, true);

            m_nCenterLink = STATUSL_CNNTING;
            if (m_NetworkPtr->Connect(m_sConnectCenter, strAddr.usPort, *strAddr.strIp) == false)
            {
                LOGV_WARN(m_FileLog, TF("[业务数据]连接同步管理服务器[%s]:%d请求失败"), *strAddr.strIp, strAddr.usPort);
            }
            else
            {
                LOGV_INFO(m_FileLog, TF("[业务数据]连接同步管理服务器[%s]:%d请求完成"), *strAddr.strIp, strAddr.usPort);
            }
        }
    }
    else
    {
        LOG_ERROR(m_FileLog, TF("[业务数据]创建连接同步管理服务器Socket失败"));
        return false;
    }
    return true;
}

bool CMasterDBServer::StartListen(void)
{
    if (m_sListenInternal != 0)
    {
        LOG_INFO(m_FileLog, TF("[业务数据]监听服务器Socket已经存在"));
        return true;
    }
    if (m_pConfig->GetAnyListen() != 0)
    {
        m_sListenInternal = m_NetworkPtr->Create(*this, m_ServerInfo.NetAddr[COMMONI_ANY].usPort);
    }
    else
    {
        m_sListenInternal = m_NetworkPtr->Create(*this, m_ServerInfo.NetAddr[COMMONI_ANY]);
    }
    bool bRet = true;
    if (m_sListenInternal != 0)
    {
        bRet = m_NetworkPtr->Listen(m_sListenInternal);
        LOGV_INFO(m_FileLog, TF("[业务数据]创建监听服务器成功, %s"), bRet ? TF("监听操作成功") : TF("监听操作失败"));
    }
    else
    {
        LOG_ERROR(m_FileLog, TF("[业务数据]创建监听服务器失败"));
    }
    return bRet;
}
//--------------------------------------
bool CMasterDBServer::Pause(bool bPause)
{
    if (bPause && (m_nStatus == STATUSS_RUN))
    {
        m_nStatus = STATUSS_PAUSE;
        LOG_INFO(m_FileLog, TF("[业务数据]暂停服务"));
        m_RoutinePtr->Pause();
        return true;
    }
    else if ((bPause == false) && (m_nStatus == STATUSS_PAUSE))
    {
        m_nStatus = STATUSS_RUN;
        LOG_INFO(m_FileLog, TF("[业务数据]允许服务"));
        m_RoutinePtr->Pause(false);
        return true;
    }
    return false;
}
//--------------------------------------
void CMasterDBServer::Stop(void)
{
    if (m_nStatus > STATUSS_NONE)
    {
        LOG_INFO(m_FileLog, TF("[业务数据]停止开始!"));
        m_nStatus = STATUSS_STOP;

        m_nServerInfo  = TRUE;
        m_nServerAck   = FALSE;
        m_nSyncInfo    = FALSE;
        m_nCommonEvent = FALSE;
        StopListen();
        StopConnectCenterServer();

        m_RoutinePtr->Stop();

        m_ServerInfo.Zero();
        m_Server[PAKT_MASTER - PAKT_MASTER].Reset();
        m_Server[PAKT_SERVICE - PAKT_MASTER].Reset();
        m_Master.SvrMap.RemoveAll();
        m_Service.SvrMap.RemoveAll();

        m_nStatus = STATUSS_INIT;
        LOG_INFO(m_FileLog, TF("[业务数据]停止完成!"));
    }
}

void CMasterDBServer::StopConnectCenterServer(void)
{
    if (m_sConnectCenter != 0)
    {
        m_NetworkPtr->Destroy(m_sConnectCenter);
        m_sConnectCenter = 0;
        LOG_INFO(m_FileLog, TF("[业务数据]销毁连接同步管理服务器Socket成功"));
    }
    m_nCenterLink = STATUSL_NONE;
}

void CMasterDBServer::StopListen(void)
{
    if (m_sListenInternal != 0)
    {
        m_NetworkPtr->Destroy(m_sListenInternal);
        m_sListenInternal = 0;
        LOG_INFO(m_FileLog, TF("[业务数据]销毁监听Socket"));
    }
}
//--------------------------------------
bool CMasterDBServer::OnTcpDispatch(const PacketPtr& PktPtr, PTCP_PARAM pTcp)
{
    // 1. PTCP_PARAM->pCache != nullptr时上层可以保存网络层申请的缓存数据
    //    PTCP_PARAM->pCache, PTCP_PARAM->index是网络层申请的缓存数据的起始地址和索引号
    // 2. PTCP_PARAM->pData为当前数据开始地址, PTCP_PARAM->stSize为当前数据大小
    // 3. 如果上层保存缓存, 设置PTCP_PARAM->pData为nullptr通知网络层不要再使用当前缓存
    // 4. 释放缓存使用MObject::sMCFree(index, pCache)
    bool bRet = true;
    if (PktPtr->GetEvent() != PAKE_LIVE)
    {
        switch (PktPtr->GetType())
        {
        case PAKT_MASTER:
        case PAKT_SERVICE:
            {
                bRet = DispatchMasterDBServer(PktPtr, pTcp);
            }
            break;
        case PAKT_CENTER:
            {
                bRet = DispatchCenterServer(PktPtr, pTcp);
            }
            break;
        default:
            {
                LOGV_WARN(m_FileLog, TF("[业务数据]%p无法识别的信令包类型[%d]数据[event=%d]"), pTcp->sSocket, PktPtr->GetType(), PktPtr->GetEvent());
                bRet = false;
            }
        }
    }
    else
    {
        CTPAKHeadBase<PAKE_LIVEACK, PAKT_MASTERDB> LiveAck;
        LiveAck.SetSrvId((USRVID)m_ServerInfo.usId);
        m_NetworkPtr->Send(pTcp->sSocket, LiveAck);
    }
    return bRet;
}

bool CMasterDBServer::DispatchCenterServer(const PacketPtr& PktPtr, PTCP_PARAM pTcp)
{
    switch (PktPtr->GetEvent())
    {
    case PAKE_LINKACK:
        {
            if (PktPtr->GetAck() == (UACK)ERRORD_OKAY)
            {
                m_nCenterLink = STATUSL_LINKED;

                NET_ADDR NetAddr;
                m_NetworkPtr->GetAddr(pTcp->sSocket, NetAddr, false);
                m_MgrHandler->OnHandle(PAKE_LINK, reinterpret_cast<uintptr_t>(&NetAddr), PAKT_CENTER);
                LOG_INFO(m_FileLog, TF("[业务数据]收到同步管理服务器注册回复包"));
                if (m_nServerAck != FALSE)
                {
                    m_RoutinePtr->AddQueue(PAKE_LINKACK, PktPtr->GetSrvId(), PAKT_CENTER);
                }
            }
            else
            {
                m_nCenterLink = STATUSL_FAILED;
                LOGV_WARN(m_FileLog, TF("[业务数据]收到同步管理服务器注册回复包, 错误信息=%d"), PktPtr->GetAck());

                m_nStatus = STATUSS_OVER;
                m_ServerInfo.OverLoad();
                DEV_WARN(TF("[业务数据]收到同步管理服务器注册回复错误, 进入超载状态!"));
                LOG_WARN(m_FileLog, TF("[业务数据]收到同步管理服务器注册回复错误, 进入超载状态!"));
            }
        }
        break;
    case PAKE_UPDATEACK:
        {
            //DEV_INFO(TF("[业务数据]收到同步管理服务器更新回复包"));
        }
        break;
    case PAKE_UNLINKACK:
        {
            m_nCenterLink = STATUSL_CNNTED;
            LOG_INFO(m_FileLog, TF("[业务数据]收到同步管理服务器注销回复包"));
            if (m_nServerAck != FALSE)
            {
                m_RoutinePtr->AddQueue(PAKE_UNLINKACK, 0, PAKT_CENTER);
            }
        }
        break;
    case PAKE_LIVEACK:
        {
        }
        break;
    default:
        {
            if ((m_nCommonEvent != FALSE) && 
                (PktPtr->GetEvent() >= PAKE_COMMON_BEGIN) &&
                (PktPtr->GetEvent() <= PAKE_COMMON_END))
            {
                m_RoutinePtr->AddQueue((Int)PktPtr->GetEvent(), *PktPtr, reinterpret_cast<ULLong>(pTcp), QUEUE_TYPE_REFCOUNT_TCP);
            }
            else
            {
                LOGV_WARN(m_FileLog, TF("[业务数据]%p无法识别的同步管理服务器信令包数据[event=%d]"), pTcp->sSocket, PktPtr->GetEvent());
            }
        }
    }
    return true;
}

bool CMasterDBServer::DispatchMasterDBServer(const PacketPtr& PktPtr, PTCP_PARAM pTcp)
{
    bool bRet = true;
    switch (PktPtr->GetEvent())
    {
    case PAKE_LINK:
        {
            if (m_nServerInfo != FALSE)
            {
                // 检测id是否重复, 如果需要id唯一的按检测结果返回, true表示id唯一, false表示id重复冲突
                m_RoutinePtr->AddQueue(PAKE_LINK, *PktPtr, reinterpret_cast<ULLong>(pTcp), QUEUE_TYPE_REFCOUNT_TCP);
            }
            if (bRet)
            {
                bRet = OnServerLink(static_cast<CNETLink*>(PktPtr.Get()), pTcp->sSocket);
            }
        }
        break;
    case PAKE_UPDATE:
        {
            bRet = OnServerUpdate(static_cast<CNETUpdate*>(PktPtr.Get()), pTcp->sSocket);
            if (m_nServerInfo != FALSE)
            {
                m_RoutinePtr->AddQueue(PAKE_UPDATE, *PktPtr, reinterpret_cast<ULLong>(pTcp), QUEUE_TYPE_REFCOUNT_TCP);
            }
        }
        break;
    case PAKE_UNLINK:
        {
            SERVER_UNLINK su;
            bRet = OnServerUnlink(PktPtr.Get(), pTcp->sSocket, su);
            if (m_nServerInfo != FALSE)
            {
                m_RoutinePtr->AddQueue(PAKE_UNLINK, su.utData, pTcp->sSocket);
            }
        }
        break;
    default:
        {
            if ((PktPtr->GetEvent() >= PAKE_ROUTINE_BEGIN) && (PktPtr->GetEvent() <= PAKE_ROUTINE_FAIL))
            {
                m_RoutinePtr->AddQueue((Int)PktPtr->GetEvent(), *PktPtr, reinterpret_cast<ULLong>(pTcp), QUEUE_TYPE_REFCOUNT_TCP);
            }
            if ((PktPtr->GetEvent() >= PAKE_SERVICE_BEGIN) && (PktPtr->GetEvent() <= PAKE_SERVICE_END))
            {
                m_RoutinePtr->AddQueue((Int)PktPtr->GetEvent(), *PktPtr, reinterpret_cast<ULLong>(pTcp), QUEUE_TYPE_REFCOUNT_TCP);
            }
            else if ((m_nCommonEvent != FALSE) &&
                     (PktPtr->GetEvent() >= PAKE_COMMON_BEGIN) &&
                     (PktPtr->GetEvent() <= PAKE_COMMON_END))
            {
                m_RoutinePtr->AddQueue((Int)PktPtr->GetEvent(), *PktPtr, reinterpret_cast<ULLong>(pTcp), QUEUE_TYPE_REFCOUNT_TCP);
            }
            else
            {
                LOGV_WARN(m_FileLog, TF("[业务数据]%p无法识别的服务器(type=%d)信令包数据[event=%d]"), pTcp->sSocket, PktPtr->GetType(), PktPtr->GetEvent());
            }
        }
    }
    return bRet;
}

bool CMasterDBServer::OnServerLink(CNETLink* pLink, Socket sSocket)
{
    bool bRet = false;
    switch (pLink->GetType())
    {
    case PAKT_MASTER:
        {
            LOGV_INFO(m_FileLog, TF("[业务数据]业务管理服务器[%p]注册"), sSocket);
            bRet = ServerLink<SVR_MASTER_MAP, PAKT_MASTER>(pLink, (ULLong)sSocket, m_Master);
        }
        break;
    case PAKT_SERVICE:
        {
            LOGV_INFO(m_FileLog, TF("[业务数据]业务功能服务器[%p]注册"), sSocket);
            bRet = ServerLink<SVR_GATE_MAP, PAKT_SERVICE>(pLink, (ULLong)sSocket, m_Service);
        }
        break;
    default:
        {
            LOGV_WARN(m_FileLog, TF("[业务数据]%p无法识别的%X服务器注册信令包数据"), sSocket, pLink->GetType());
        }
    }
    if (bRet)
    {
        // 3.设置为对应服务器类型
        m_NetworkPtr->SetAttr(sSocket, (pLink->GetType() == PAKT_MASTER) ? PAKT_MASTER_MASTERDB : PAKT_SERVICE_MASTERDB);
        // 4.发送注册回执包
        CTPAKHeadBase<PAKE_LINKACK, PAKT_MASTERDB> LinkAck;
        LinkAck.SetSrvId((USRVID)m_ServerInfo.usId);
        m_NetworkPtr->Send(sSocket, LinkAck);
    }
    else
    {
        LOGV_WARN(m_FileLog, TF("[业务数据]服务器(type=%d)%p注册时失败"), pLink->GetType(), sSocket);
    }
    return bRet;
}

bool CMasterDBServer::OnServerUpdate(CNETUpdate* pUpdate, Socket sSocket)
{
    bool bRet = false;
    switch (pUpdate->GetType())
    {
    case PAKT_MASTER:
        {
            bRet = ServerUpdate<SVR_MASTER_MAP, PAKT_MASTER>(pUpdate, (ULLong)sSocket, m_Master);
        }
        break;
    case PAKT_SERVICE:
        {
            bRet = ServerUpdate<SVR_GATE_MAP, PAKT_SERVICE>(pUpdate, (ULLong)sSocket, m_Service);
        }
        break;
    default:
        {
            LOGV_WARN(m_FileLog, TF("[业务数据]%p无法识别的%X服务器更新信令包数据"), sSocket, pUpdate->GetType());
        }
    }
    if (bRet)
    {
        // 发送更新回执包
        CTPAKHeadBase<PAKE_UPDATEACK, PAKT_MASTERDB> UpdateAck;
        m_NetworkPtr->Send(sSocket, UpdateAck);
    }
    else
    {
        LOGV_WARN(m_FileLog, TF("[业务数据]服务器(type=%d)%p更新信息异常"), pUpdate->GetType(), sSocket);
    }
    return bRet;
}

bool CMasterDBServer::OnServerUnlink(CPAKHeadBase* pUnlink, Socket sSocket, SERVER_UNLINK& su)
{
    bool bRet = false;
    switch (pUnlink->GetType())
    {
    case PAKT_MASTER:
        {
            LOGV_INFO(m_FileLog, TF("[业务数据]业务管理服务器[%p]注销"), sSocket);
            bRet = ServerUnlink<SVR_MASTER_MAP, PAKT_MASTER>(sSocket, m_Master, su);
        }
        break;
    case PAKT_SERVICE:
        {
            LOGV_INFO(m_FileLog, TF("[业务数据]业务功能服务器[%p]注销"), sSocket);
            bRet = ServerUnlink<SVR_GATE_MAP, PAKT_SERVICE>(sSocket, m_Service, su);
        }
        break;
    default:
        {
            LOGV_WARN(m_FileLog, TF("[业务数据]%p无法识别的%X服务器注销信令包数据"), sSocket, pUnlink->GetType());
        }
    }
    if (bRet)
    {
        // 3.设置为无效服务器类型
        m_NetworkPtr->SetAttr(sSocket, PAKT_NONE);
        // 4.发送注销回执包
        CTPAKHeadBase<PAKE_UNLINKACK, PAKT_MASTERDB> UnlinkAck;
        m_NetworkPtr->Send(sSocket, UnlinkAck);
    }
    return bRet;
}
//--------------------------------------
bool CMasterDBServer::OnTcpAccept(Socket sAccept, Socket sListen)
{
    UNREFERENCED_PARAMETER(sListen);
    assert(sListen == m_sListenInternal);
    if (m_nStatus == STATUSS_RUN)
    {
        UShort  usPort = 0;
        CString strAddr;
        m_NetworkPtr->GetAddr(sAccept, strAddr, usPort);

        DEV_INFO(TF("[业务数据]服务器[%s]:%d连接完成!"), *strAddr, usPort);
        LOGV_DUMP(m_FileLog, TF("[业务数据]服务器[%s]:%d连接完成!"), *strAddr, usPort);

        m_ServerInfo.IncrTotal();
        return true;
    }
    else
    {
        LOGV_WARN(m_FileLog, TF("[业务数据]业务数据处于暂停状态!"));
    }
    return false;
}
//--------------------------------------
bool CMasterDBServer::OnTcpConnect(UInt uError, Socket sConnect)
{
    if (sConnect == m_sConnectCenter)
    {
        if (uError == 0)
        {
            m_nCenterLink = STATUSL_CNNTED;
            LinkCenterServer();
        }
        else
        {
            //DEV_INFO(TF("[业务数据]连接同步管理服务器失败%X!"), uError);
            LOGV_WARN(m_FileLog, TF("[业务数据]连接同步管理服务器失败%X!"), uError);
        }
    }
    return true;
}

void CMasterDBServer::LinkCenterServer(void)
{
    if (m_nCenterLink == STATUSL_CNNTED)
    {
        m_ServerInfo.usStatus = STATUSU_LINK;

        CMasterDBLink Link;
        Link.SetServerStatus(m_ServerInfo);

        CStream& Stream = Link.Alloc(m_NetworkPtr);
        if (Stream.IsWrite())
        {
            m_ServerInfo.Addr(Stream);
            if (m_nSyncInfo != FALSE)
            {
                m_RoutinePtr->AddQueue(PAKE_LINK, Stream, PAKT_CENTER);
            }
            m_nCenterLink = STATUSL_LINKING;
            Link.Send(m_sConnectCenter, m_NetworkPtr);
        }
        else
        {
            DEV_WARN(TF("[业务数据]向同步管理服务器注册时创建网络数据流异常!"));
            LOG_WARN(m_FileLog, TF("[业务数据]向同步管理服务器注册时创建网络数据流异常!"));
        }
    }
}

void CMasterDBServer::UnlinkCenterServer(void)
{
    if (m_nCenterLink == STATUSL_LINKED)
    {
        m_nCenterLink = STATUSL_CNNTED;
        CTPAKHeadBase<PAKE_UNLINK, PAKT_MASTERDB> Unlink;
        m_NetworkPtr->Send(m_sConnectCenter, Unlink);
    }
}
//--------------------------------------
bool CMasterDBServer::OnTcpClose(Socket sSocket, ULLong ullLiveData)
{
    if (m_nStatus == STATUSS_STOP)
    {
        return false;
    }
    if (sSocket == m_sConnectCenter)
    {
        m_sConnectCenter = 0;
        m_nCenterLink = STATUSL_NONE;
        m_MgrHandler->OnHandle(PAKE_UNLINK, 0, PAKT_CENTER);
        DEV_WARN(TF("[业务数据]连接同步管理服务器断开"));
        LOG_WARN(m_FileLog, TF("[业务数据]连接同步管理服务器断开"));

        if (m_nServerAck != FALSE)
        {
            m_RoutinePtr->AddQueue(PAKE_UNLINKACK, 0, PAKT_CENTER);
        }
    }
    if (sSocket == m_sListenInternal)
    {
        m_ServerInfo.WarnLoad();

        m_sListenInternal = 0;
        DEV_WARN(TF("[业务数据]监听关闭, 进入告警状态"));
        LOG_WARN(m_FileLog, TF("[业务数据]监听关闭, 进入告警状态"));
    }
    else
    { // 单个服务器断开
        SERVER_UNLINK su;
        switch (ullLiveData)
        {
        case PAKT_MASTER_MASTERDB:
            {
                ServerUnlink<SVR_MASTER_MAP, PAKT_MASTER>(sSocket, m_Master, su);
                LOGV_INFO(m_FileLog, TF("[业务数据]业务管理服务器[%p]断开"), sSocket);
            }
            break;
        case PAKT_SERVICE_MASTERDB:
            {
                ServerUnlink<SVR_GATE_MAP, PAKT_SERVICE>(sSocket, m_Service, su);
                LOGV_INFO(m_FileLog, TF("[业务数据]业务功能服务器[%p]断开"), sSocket);
            }
            break;
        default:
            {
            }
        }
        if (m_nServerInfo != FALSE)
        {
            m_RoutinePtr->AddQueue(PAKE_UNLINK, su.utData, sSocket);
        }
        m_ServerInfo.DecrTotal();
    }
    return true;
}
//--------------------------------------
bool CMasterDBServer::CheckConnectCenterServer(void)
{
    if (m_nCenterLink < STATUSL_CNNTED)
    {
        if (m_nCenterLink == STATUSL_NONE)
        {
            StartConnectCenterServer();
        }
        else
        {
            --m_nCenterLink;
        }
    }
    else if (m_nCenterLink < STATUSL_LINKED)
    {
        if (m_nCenterLink == STATUSL_CNNTED)
        {
            LinkCenterServer();
        }
        else
        {
            --m_nCenterLink;
        }
    }
    return true;
}

bool CMasterDBServer::CheckListen(void)
{
    if (m_sListenInternal == 0)
    {
        if (StartListen() && m_ServerInfo.IsWarnLoad())
        {
            DEV_WARN(TF("[业务数据]监听重开, 尝试消除告警状态"));
            LOG_WARN(m_FileLog, TF("[业务数据]监听重开, 尝试消除告警状态"));
            m_ServerInfo.Clear();
        }
    }
    return true;
}

bool CMasterDBServer::SyncServerInfo(void)
{
    if (m_ServerInfo.usStatus == STATUSU_SYNC)
    {
        if (m_nCenterLink == STATUSL_LINKED)
        {
            CMasterDBUpdate Update;
            Update.SetServerStatus(m_ServerInfo);

            CStream& Stream = Update.Alloc(m_NetworkPtr);
            if (Stream.IsWrite())
            {
                m_ServerInfo.Addr(Stream);
                if (m_nSyncInfo != FALSE)
                {
                    m_RoutinePtr->AddQueue(PAKE_UPDATE, Stream, PAKT_CENTER);
                }
                Update.Send(m_sConnectCenter, m_NetworkPtr);
            }
        }
        m_ServerInfo.usStatus = STATUSU_OKAY;
        return (m_MgrHandler->OnHandle(PAKE_SYNC, reinterpret_cast<uintptr_t>(&m_ServerInfo), PAKT_MASTERDB) == RET_OKAY);
    }
    else if (m_nCenterLink == STATUSL_LINKED)
    {
        CTPAKHeadBase<PAKE_LIVE, PAKT_MASTERDB> Live;
        Live.SetSrvId((UACK)m_ServerInfo.usId);
        m_NetworkPtr->Send(m_sConnectCenter, Live);
    }
    bool bRet = false;
    if (m_Server[PAKT_MASTER - PAKT_MASTER].usStatus == STATUSU_SYNC)
    {
        //m_Master.Update();
        m_Server[PAKT_MASTER - PAKT_MASTER].usStatus = STATUSU_OKAY;
        m_MgrHandler->OnHandle(PAKE_SYNC, reinterpret_cast<uintptr_t>(m_Server + (PAKT_MASTER - PAKT_MASTER)), PAKT_MASTER);
        bRet = true;
    }
    if (m_Server[PAKT_SERVICE - PAKT_MASTER].usStatus == STATUSU_SYNC)
    {
        //m_Service.Update();
        m_Server[PAKT_SERVICE - PAKT_MASTER].usStatus = STATUSU_OKAY;
        m_MgrHandler->OnHandle(PAKE_SYNC, reinterpret_cast<uintptr_t>(m_Server + (PAKT_SERVICE - PAKT_MASTER)), PAKT_SERVICE);
        bRet = true;
    }
    return bRet;
}

bool CMasterDBServer::LoadExtConfig(void)
{
    CStringFix strPath;
    m_pConfig->GetServerExtConfig(CServerConfig::CFG_LOAD_MASTERDB, strPath);

    LOGV_INFO(m_FileLog, TF("[业务数据]ExtConfig=%s"), *strPath);

    CFileReadStream Reader;
    if (Reader.Create(*strPath))
    {
        CKVNode  KVNode;
        CKVStore KVStore;
        if (KVStore.Load(KVNode, Reader))
        {
            if (KVNode.Find(TF("FrameworkRoutine")))
            {
                return LoadExtRoutine(KVNode);
            }
            else
            {
                LOGV_WARN(m_FileLog, TF("[业务数据]无法找到ExtConfig=%s文件内的节点FrameworkRoutine"), *strPath);
            }
        }
        else
        {
            LOGV_WARN(m_FileLog, TF("[业务数据]解析ExtConfig=%s文件内容失败"), *strPath);
        }
    }
    else
    {
        LOGV_WARN(m_FileLog, TF("[业务数据]打开ExtConfig=%s文件不存在"), *strPath);
    }

    LOG_INFO(m_FileLog, TF("[业务数据]默认加载同目录下框架例程模块"));
    CStringKey strObjectKey = TF("C");
    strObjectKey += CServerConfig::MasterDBRoutine;

    CStringKey strModuleKey = CServerConfig::CurFolder;
#if (__PLATFORM_TARGET__ == PLATFORM_TARGET_LINUX)
    strModuleKey += CServerConfig::LibPrefix;
#endif
    strModuleKey += CServerConfig::MasterDBRoutine;
    strModuleKey += CServerConfig::LibExt;

    return CreateRTTIObject(*strObjectKey, CServerConfig::MasterDBRoutine, *strModuleKey);
}

bool CMasterDBServer::LoadExtRoutine(CKVNode& Root)
{
    // {
    //     "FrameworkRoutine":{
    //         "Name": "MasterDB-Routine",
    //         "Object": "MasterDB-Routine class name",
    //         "Module": "MasterDB-Routine module name",
    //     },
    //  ...
    // }
    CKVString strName;
    CKVString strObject;
    CKVString strModule;

    CKVNode& Routine = Root[TF("FrameworkRoutine")];
    Routine[TF("Name")].GetString(strName);
    Routine[TF("Object")].GetString(strObject);
    Routine[TF("Module")].GetString(strModule);
#if (__PLATFORM_TARGET__ == PLATFORM_TARGET_LINUX)
    strModule.Insert(0, CServerConfig::LibPrefix);
#endif
    strModule += CServerConfig::LibExt;

    return CreateRTTIObject(*strObject, *strName, *strModule);
}

bool CMasterDBServer::CreateRTTIObject(PCXStr pszObject, PCXStr pszName, PCXStr pszModule)
{
    assert(m_RoutinePtr == nullptr);
    if (CObjectTraits::Load<ICommonRoutine>(pszName, pszModule, m_RoutinePtr, pszObject))
    {
        LOGV_INFO(m_FileLog, TF("[业务数据]RTTI load --- Object=%s, Name=%s, Module=%s --- %p"), pszObject, pszName, pszModule, m_RoutinePtr.Get());
        return (m_RoutinePtr->Init() == (UInt)RET_OKAY);
    }
    LOGV_ERROR(m_FileLog, TF("[业务数据]RTTI load --- Object=%s, Name=%s, Module=%s --- Failed!"), pszObject, pszName, pszModule);
    return false;
}

bool CMasterDBServer::UnloadExtConfig(void)
{
    return UnloadExtRoutine();
}

bool CMasterDBServer::UnloadExtRoutine(void)
{
    if (m_RoutinePtr != nullptr)
    {
        CString strName = m_RoutinePtr->GetRTTI().GetName();
        m_RoutinePtr->Exit();
        m_RoutinePtr = nullptr;
        CObjectTraits::Unload<ICommonRoutine>(*strName);
        return true;
    }
    return false;
}


